#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2021/4/24 19:26
# @Author  : Grayson Liu
# @Email   : graysonliu@foxmail.com
# @File    : SetParameterRangeDialog.py
from PyQt5.QtGui import QIntValidator, QDoubleValidator
from PyQt5.QtWidgets import QDialog, QFileDialog, QMessageBox

from ui.Ui_SetParameterRangeDialog import Ui_SetParameterRangeDialog
from CustomSignal import CustomSignal


class SetParameterRangeDialog(QDialog, Ui_SetParameterRangeDialog):
    """
    设置参数实验参数范围的对话框
    """
    global_signal = CustomSignal()

    def __init__(self, method_info: dict, parameter_info: dict, parent=None):
        """
        初始化
        :param method_info: 从MethodList中截取的方法信息
        :param parameter_info: 从method_data中截取的方法和参数信息
        :param parent: 父窗体
        """
        super(SetParameterRangeDialog, self).__init__(parent)
        self.setupUi(self)

        # 成员变量
        self.parameter_info = parameter_info

        # 将ParaExpForm传递而来的输出信息显示在当前界面上
        self.lblParameterName.setText("方法{}的参数{}".format(method_info["name"], parameter_info["name"]))
        self.lblParameterConstraint.setText("{}, max: {}, min: {}, {}".format(parameter_info["type"],
                                                                              parameter_info["max"],
                                                                              parameter_info["min"],
                                                                              parameter_info["constraints"]))
        # 限定当前输入框的输入，分仅限int型和仅限float型
        if parameter_info["type"] == "int":
            self.txtStartValue.setValidator(QIntValidator())
            self.txtStepValue.setValidator(QIntValidator())
            self.txtEndValue.setValidator(QIntValidator())
        else:
            self.txtStartValue.setValidator(QDoubleValidator())
            self.txtStepValue.setValidator(QDoubleValidator())
            self.txtEndValue.setValidator(QDoubleValidator())

        # 绑定信号和槽
        self.btnCancel.clicked.connect(self.cancel_parameter_range)
        self.btnConfirm.clicked.connect(self.confirm_parameter_range)

    def confirm_parameter_range(self):
        """
        对话框“确认”按钮的槽函数
        :return:
        """
        start_value = eval(self.txtStartValue.text())
        step_value = eval(self.txtStepValue.text())
        end_value = eval(self.txtEndValue.text())
        parameter_range = list(range(start_value, end_value, step_value))
        # 生成参数取值列表后，依次校验，如果通过则发信号给ParaExpForm
        for i in parameter_range:
            # 发现某一参数校验不通过
            if not self.__validate_parameter(i, self.parameter_info):
                QMessageBox.warning(self,
                                    "参数错误",
                                    "参数不符合限定要求，请检查。\n参数列表：{}\n参数：{}".format(parameter_range, i),
                                    QMessageBox.Ok)
                return
        # 若参数全部通过
        QMessageBox.information(self, "参数正确", "参数列表：{}".format(parameter_range), QMessageBox.Ok)
        # 给ParaExpForm窗体发信号
        SetParameterRangeDialog.global_signal.set_parameter_range.emit(parameter_range)
        self.close()

    def __validate_parameter(self, value, parameter):
        """
        私有方法，用于检验参数是否符合限定要求
        :param value: 用户输入的参数值
        :param parameter: 描述该参数的字典
        :return: True或False
        """
        if parameter["type"] != type(value).__name__:
            return False
        if value < parameter["min"] or value > parameter["max"]:
            return False
        if parameter["constraints"] == "odd":
            if value % 2 != 1:
                return False
        return True

    def cancel_parameter_range(self):
        """
        对话框”取消“按钮的槽函数
        :return:
        """
        SetParameterRangeDialog.global_signal.update_text.emit("取消参数范围设置。")
        self.close()
